﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CompareDataStructure.cs" company="">
//   
// </copyright>
// <summary>
//   The compare data structure.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace DbDiff.Common.Comparer
{
    using System;
    using System.Data;
    using System.Linq;
    using DataAccess;
    using Helper;
    using Model;

    /// <summary>
    /// The compare data structure.
    /// </summary>
    public abstract class CompareDataStructure
    {
        #region private var

        /// <summary>
        /// The database compare
        /// </summary>
        protected readonly DatabaseCompare cmp = null;

        /// <summary>
        /// The error string.
        /// </summary>
        protected string errorString = string.Empty;

        /// <summary>
        /// The dr cmp.
        /// </summary>
        protected readonly DataRowCompare drCmp = null;

        /// <summary>
        /// The object type.
        /// </summary>
        protected readonly DatabaseObjectTypes objectType;

        /// <summary>
        /// The row column name.
        /// </summary>
        protected DataRowCompareIndex rowColumnName;

        /// <summary>
        /// The dv 1 name.
        /// </summary>
        protected DataViewDs dv1Name = null;

        /// <summary>
        /// The dv 2 name.
        /// </summary>
        protected DataViewDs dv2Name = null;

        /// <summary>
        /// The dv 1 key.
        /// </summary>
        protected DataViewDs dv1Key = null;

        /// <summary>
        /// The dv 2 key.
        /// </summary>
        protected DataViewDs dv2Key = null;

        /// <summary>
        /// The index name.
        /// </summary>
        protected string indexName = string.Empty;

        #endregion private var

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="CompareDataStructure"/> class.
        /// </summary>
        /// <param name="databaseCompare">
        /// The db compare.
        /// </param>
        /// <param name="objectType">
        /// The object type.
        /// </param>
        protected CompareDataStructure(DatabaseCompare databaseCompare, DatabaseObjectTypes objectType)
        {
            this.cmp = databaseCompare;
            this.objectType = objectType;
            this.drCmp = new DataRowCompare(this.cmp.ErrorMessageTables, this.cmp.Diff, this.cmp.DatabaseInfoBaseLeft, this.cmp.RegMatch);
        }

        #endregion Constructor

        #region Findrows

        /// <summary>
        /// The find rows.
        /// </summary>
        /// <param name="dv">
        /// The dv.
        /// </param>
        /// <param name="isSort">
        /// The is sort.
        /// </param>
        /// <returns>
        /// </returns>
        protected virtual DataRowView[] FindRows(DataViewDs dv, bool isSort)
        {
            var obj = new object[] { this.cmp.CurrentOwner, this.cmp.CurrentName };
            return dv.FindRows(obj, isSort);
        }

        #endregion Findrows

        #region Add Dataset Diff data row

        /// <summary>
        /// The add diff.
        /// </summary>
        /// <param name="missingMsg">
        /// The missing msg.
        /// </param>
        private void AddDiff(string missingMsg)
        {
            this.cmp.Diff.dbDiffDetails.AdddbDiffDetailsRow(
                this.cmp.CurrentOwner,
                this.cmp.CurrentName,
                this.cmp.CurrentField,
                this.indexName,
                missingMsg,
                CompareMsg.MsgDb1Missing,
                this.cmp.ObjectID,
                CompareMsg.MsgFalse,
                CompareMsg.MsgTrue,
                this.objectType.ToString());
        }

        #endregion

        #region CompareALL

        #region Compare childrows

        /// <summary>
        /// The compare child rows.
        /// </summary>
        public virtual void CompareChildRows()
        {
        }

        #endregion Compare childrows

        #region Compare left side

        /// <summary>
        /// The compare left.
        /// </summary>
        public virtual void CompareLeft()
        {
            DataRowView[] foundRows = this.FindRows(this.dv1Name, false);

            if (foundRows.Length <= 0)
            {
                return;
            }

            //var x = (from t in foundRows
            //        select new
            //                   {
            //                       rowView = t,
            //                       index = this.dv2Key.Find(this.dv1Key.GetRowKeysValue(t.Row)),
            //                       localField = Convert.ToString(t.Row.ItemArray[(int)this.rowColumnName])
            //                   }).AsParallel();

            //// missing fields
            //var missingFields = (from t in x where t.index == -1 select t.localField).AsParallel();

            //foreach (var missingField in missingFields)
            //{
            //    this.errorString += (this.errorString != string.Empty ? "," : string.Empty) +
            //                            string.Format("Field missing(Db1):{0}", missingField);

            //    this.cmp.CurrentField = missingField;
            //    this.AddDiff(CompareMsg.MsgDb2Missing);
            //}

            //var existsFields = (from t in x where t.index != -1 select new {t,item =this.drCmp.CompareRow(
            //                        t.rowView.Row,
            //                        this.dv2Key[t.index].Row,
            //                        this.objectType,
            //                        (int)this.rowColumnName,
            //                        this.cmp.CurrentOwner,
            //                        this.cmp.CurrentName,
            //                        t.localField,
            //                        this.indexName,
            //                        this.cmp.ObjectID)}).AsParallel();

            //foreach (var existsField in existsFields)
            //{
            //    this.cmp.CurrentField = existsField.t.localField;
            //    if (existsField.item.Length != 0)
            //    {
            //        this.errorString += (this.errorString != string.Empty ? "," : string.Empty) +
            //                            string.Format("Field:{0} ", this.cmp.CurrentField) + existsField.item;
            //    }
                            
            //    this.CompareChildRows();
            //}

            //return;
            ////todo remove return

            foreach (DataRowView t in foundRows)
            {
                this.cmp.CurrentField = Convert.ToString(t.Row.ItemArray[(int)this.rowColumnName]);
                int rowindex = this.dv2Key.Find(this.dv1Key.GetRowKeysValue(t.Row));

                if (rowindex != -1)
                {
                    string item = this.drCmp.CompareRow(
                        t.Row,
                        this.dv2Key[rowindex].Row,
                        this.objectType, 
                        (int)this.rowColumnName,
                        this.cmp.CurrentOwner,
                        this.cmp.CurrentName,
                        this.cmp.CurrentField,
                        this.indexName,
                        this.cmp.ObjectID);

                    if (item.Length != 0)
                    {
                        this.errorString += (this.errorString != string.Empty ? "," : string.Empty) +
                                            string.Format("Field:{0} ", this.cmp.CurrentField) + item;
                    }

                    this.CompareChildRows();
                }
                else
                {
                    // nincs ilyen mező
                    this.errorString += (this.errorString != string.Empty ? "," : string.Empty) +
                                        string.Format("Field missing(Db1):{0}", this.cmp.CurrentField);
                    this.AddDiff(CompareMsg.MsgDb2Missing);
                }
            }
        }

        #endregion

        #region Compare right side

        /// <summary>
        /// The compare right.
        /// </summary>
        public virtual void CompareRight()
        {
            DataRowView[] foundRows = this.FindRows(this.dv2Name, false);

            if (foundRows.Length <= 0)
            {
                return;
            }

            // exists
            var query = (from t in foundRows where this.dv1Key.Find(this.dv2Key.GetRowKeysValue(t.Row)) == -1 select t).AsParallel();
            foreach (var t in query)
            {
                this.cmp.CurrentField = Convert.ToString(t.Row.ItemArray[(int)this.rowColumnName]);
                this.errorString += (this.errorString != string.Empty ? "," : string.Empty) +
                                    string.Format("Field missing(Db2):{0}", this.cmp.CurrentField);
                this.AddDiff(CompareMsg.MsgDb1Missing);
            }
        }

        #endregion

        #region Compare

        /// <summary>
        /// The compare.
        /// </summary>
        /// <returns>
        /// The compare.
        /// </returns>
        public virtual string Compare()
        {
            this.CompareLeft();
            this.CompareRight();

            return this.errorString;
        }

        #endregion Compare

        #endregion CompareALL
    }

}
